<?php

namespace App\Http\Controllers;

use App\Events\OrderReviewed;
use App\Exceptions\CouponCodeUnavailableException;
use App\Exceptions\InvalidRequestException;
use App\Http\Requests\ApplyRefundRequest;
use App\Http\Requests\OrderRequest;
use App\Http\Requests\SendReviewRequest;
use App\Models\CouponCode;
use App\Models\Order;
use App\Services\OrderService;
use App\Models\UserAddress;
use Carbon\Carbon;

class OrdersController extends Controller
{
    protected $orderService;

    public function __construct(OrderService $orderService)
    {
        $this->orderService = $orderService;
    }

    /**
     * 订单列表
     *
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
     */
    public function index()
    {
        $orders = $this->orderService->get();
        return view('orders.index', compact('orders'));
    }

    /**
     * 提交订单
     *
     * @param OrderRequest $request
     * @return mixed
     */
    public function store(OrderRequest $request)
    {
        $address = UserAddress::find($request->input('address_id'));
        $coupon = null;
        if ($code = $request->input('coupon_code')){
            $coupon = CouponCode::where('code', $code)->first();
            if (!$coupon){
                throw new CouponCodeUnavailableException('优惠券不存在');
            }
        }
        return $this->orderService->store($request->user(), $address, $request->input('remark'), $request->input('items'), $coupon);
    }

    /**
     * 订单详情
     *
     * @param Order $order
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
     */
    public function show(Order $order)
    {
        $this->authorize('own', $order);

        // load() 是在已经查询出来的模型上调用，而 with() 则是在 ORM 查询构造器上调用。
        $order->load(['items.product', 'items.productSku']);
        return view('orders.show', compact('order'));
    }

    public function received(Order $order)
    {
        $this->authorize('own', $order);

        // 判断订单的发货状态是否为已发货
        if ($order->ship_status !== Order::SHIP_STATUS_DELIVERED){
            throw new InvalidRequestException('发货状态不正确');
        }

        // 更新订单状态为已收到
        $order->update([
            'ship_status' => Order::SHIP_STATUS_RECEIVED
        ]);

        return $order;
    }

    /**
     * 评价
     *
     * @param Order $order
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
     * @throws InvalidRequestException
     * @throws \Illuminate\Auth\Access\AuthorizationException
     */
    public function review(Order $order)
    {
        $this->authorize('own', $order);
        if (!$order->paid_at){
            throw new InvalidRequestException('该订单未支付，不可评价');
        }

        return view('orders.review', ['order' => $order->load('items.product', 'items.productSku')]);
    }

    public function sendReview(SendReviewRequest $request, Order $order)
    {
        $this->authorize('own', $order);
        if (!$order->paid_at){
            throw new InvalidRequestException('该订单未支付，不可评价');
        }

        if ($order->reviewed){
            throw new InvalidRequestException('该订单已评价，不可重复提交');
        }

        $reviews = $request->input('reviews');
        \DB::transaction(function() use ($order, $reviews){
            foreach ($reviews as $review){
                $orderItem = $order->items()->find($review['id']);
                $orderItem->update([
                    'rating' => $review['rating'],
                    'review' => $review['review'],
                    'reviewed_at' => Carbon::now(),
                ]);
            }

            $order->update([
                'reviewed' => true
            ]);

            event(new OrderReviewed($order));
        });

        return redirect()->back();
    }

    /**
     * 申请退款
     *
     * @param ApplyRefundRequest $request
     * @param Order $order
     * @return Order
     * @throws InvalidRequestException
     * @throws \Illuminate\Auth\Access\AuthorizationException
     */
    public function applyRefund(ApplyRefundRequest $request, Order $order)
    {
        $this->authorize('own', $order);

        // 判断订单是否已支付
        if (!$order->paid_at){
            throw new InvalidRequestException('该订单未支付，不可退款');
        }

        // 判断订单退款状态是否正确
        if ($order->refund_status !== Order::REFUND_STATUS_PENDING){
            throw new InvalidRequestException('该订单已申请过退款，请勿重复申请');
        }

        // 将用户输入的退款理由放到订单的extra字段中
        $extra = $order->extra ?: [];
        $extra['refund_reason'] = $request->input('reason');
        $order->update([
            'refund_status' => Order::REFUND_STATUS_APPLIED,
            'extra' =>$extra,
        ]);

        return $order;
    }
}
